﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace yuege
{
    class Program
    {
        static string root = Path.GetFullPath("C:/jenkins/OP/Android/OPProject/");
        public static void Main()
        {
            if (!File.Exists("allpath"))
            {
                var result = new List<string>(Directory.GetFileSystemEntries(root, "*.*", SearchOption.AllDirectories).OrderBy(p => p));
                result = result.Select(p => p.Replace(root, "").Replace("\\", "/")).Where(p => p.StartsWith("Assets"))
                    .Where(p => !p.EndsWith(".meta"))
                    .Where(p => !p.EndsWith(".assetbundleroot"))
                    .Where(p => !p.EndsWith(".assetbundlerule"))
                    .ToList();
                File.WriteAllLines("allpath", result);
            }

            var allPaths = File.ReadAllLines("allpath");

            foreach (var configFile in new DirectoryInfo(root).GetFiles("rule.txt").OrderBy(p => p.FullName))
            {
                string configFilePath = configFile.FullName.Replace('\\', '/');

                string[] configs = File.ReadAllLines(configFilePath);

                //匹配出符合条件的路径
                var selectedPaths = new Dictionary<string, string>();
                var removePaths = new HashSet<string>();
                foreach (var config in configs)
                {
                    if (string.IsNullOrEmpty(config)) continue;
                    if (config.StartsWith("--")) continue;

                    var matchPath = config;
                    bool isRemove = false;
                    switch (matchPath[0])
                    {
                        case '!':
                            //识别是否是排除配置
                            isRemove = true;
                            matchPath = matchPath.Substring(1);
                            break;
                        default:
                            break;
                    }

                    var regString = $"^{matchPath.Replace("**", ".+").Replace("*", "[^/]+")}$";
                    var reg = new System.Text.RegularExpressions.Regex(regString, System.Text.RegularExpressions.RegexOptions.IgnoreCase);
                    foreach (var path in allPaths)
                    {
                        if (reg.IsMatch(path))
                        {
                            if (isRemove)
                            {
                                removePaths.Add(path);
                            }
                            else
                            {
                                selectedPaths[path] = matchPath;
                            }
                        }
                    }
                }
                //将不在移除列表中的路径进行勾选
                var result = selectedPaths.Keys.Except(removePaths).Select(p => $"{selectedPaths[p]};{p}").ToArray();
                result = selectedPaths.Keys.Except(removePaths).ToArray();
                foreach (var selectedPath in result)
                {
                    //string guid = AssetDatabase.AssetPathToGUID(selectedPath); // 获取GUID
                    //setting.CreateOrMoveEntry(guid, group); // 通过GUID勾选
                }

                StringBuilder stringBuilder = OutBuild(allPaths, result);
                //File.WriteAllText(Path.Combine(configFile.Directory.FullName, $".{ Path.GetFileNameWithoutExtension(configFilePath)}.bak.txt"), stringBuilder.ToString());
                File.WriteAllLines(Path.Combine(configFile.Directory.FullName, $".{ Path.GetFileNameWithoutExtension(configFilePath)}.bak"), result);
            }
        }

        static string Replace(string path)
        {
            return path.Replace(Environment.CurrentDirectory, "").Replace("\\", "/").Replace("/", "@");
        }

        private static StringBuilder OutBuild(string[] allPaths, string[] result)
        {
            StringBuilder stringBuilder = new StringBuilder();

            var haha = result.Select(p => new { p, full = Path.Combine(root, p) });

            List<string> bundlelist = new List<string>();

            var hashSet = new HashSet<string>();
            var files = haha.Where(p => File.Exists(p.full)).ToList();
            hashSet.UnionWith(files.Select(p => p.full));

            //处理文件夹
            foreach (var item in haha.Where(p => Directory.Exists(p.full)))
            {
                //var file =  Directory.GetFiles(item.full, "*.*").Except(hashSet);
                //hashSet.UnionWith(file);
                bundlelist.Add(Replace(item.p) + ".bundle");
            }
            //处理文件

            var sorts = files.OrderBy(p => p.p.Length).ThenBy(p => p.p)
                .Select(p => p.p)
                .Select(p => new FileInfo(p))
                .ToList();

            foreach (var item in sorts.GroupBy(p => p.Directory.FullName))
            {
                foreach (var file in sorts.Where(p => p.Name.Contains("_")).GroupBy(p => p.Name.Substring(0, p.Name.LastIndexOf("_"))))
                {
                    bundlelist.Add(Replace(item.Key + file.Key) + ".bundle");
                }
                foreach (var file in sorts.Where(p => !p.Name.Contains("_")).GroupBy(p => Path.GetFileNameWithoutExtension(p.FullName)))
                {
                    bundlelist.Add(Replace(item.Key + file.Key) + ".bundle");
                }
            }

            File.WriteAllLines(".bak.txt", bundlelist);





            //foreach (var item in result)
            //{
            //    stringBuilder.AppendLine(item);
            //    var path = Path.Combine(root, item);
            //    if (Directory.Exists(path))
            //    {
            //        foreach (var file in Directory.GetFiles()))
            //        {
            //            stringBuilder.Append("\t");
            //            stringBuilder.AppendLine(file);
            //        }
            //    }
            //    else if (File.Exists(path))
            //    {
            //        stringBuilder.Append("\t");
            //        stringBuilder.AppendLine(item);
            //    }
            //    else
            //    {
            //        throw new Exception();
            //    }
            //}

            return stringBuilder;
        }
    }

    class Program2
    {
        public static void Main()
        {
            var dd = "dsgsdhsfhh";
            Console.WriteLine(dd.Take(0).ToString());
        }
    }

    public class Program21
    {
        public static void Main()
        {
            var root = Path.GetFullPath("C:/jenkins/OP/Android/OPProject/");
            var lines = File.ReadAllLines($"{root}/Library/haahah1").Select(p => new FileInfo(Path.GetFullPath(root + p))).ToArray();
            var dirs = lines.GroupBy(p => p.Directory.FullName).ToDictionary(p => p.Key, p => p.ToArray());

            foreach (var item in dirs)
            {
                var path = Path.Combine(item.Key, ".assetbundlerule");
                if (File.Exists(path))
                {
                    if (int.TryParse(File.ReadAllText(path), out int take))
                    {
                        //从前往后拾取几个_分割的
                        foreach (var files in GroupByName(item.Value, p => string.Join("_", Path.GetFileNameWithoutExtension(p.Name).Split(new[] { '_' }, take + 1).Take(take))))
                        {
                            //文件夹内的前缀相同的为一个bundle,无关后缀
                            CreateBundle(Path.Combine(item.Key, files.Key), files.Value);
                        }
                        continue;
                    }
                    else
                    {
                        foreach (var files in GroupByName(item.Value, p => Path.GetFileNameWithoutExtension(p.FullName)))
                        {
                            //文件夹内名称相同的为一个bundle,无关后缀
                            CreateBundle(Path.Combine(item.Key, files.Key), files.Value);
                        }
                    }
                }
                else
                {
                    //文件夹内的为一个bundle
                    var fileInfo = new FileInfo("test/" + item.Key.Replace(root, "").Replace("\\", "@") + ".bundle");
                    CreateBundle(item.Key, item.Value);
                }
            }

            Dictionary<string, List<FileInfo>> GroupByName(IEnumerable<FileInfo> fileInfos, Func<FileInfo, string> func)
            {
                return fileInfos.GroupBy(func, StringComparer.OrdinalIgnoreCase).OrderByDescending(p => p.Key.Length).ThenBy(p => p.Key).ToDictionary(p => p.Key, p => p.ToList());
            }


            void CreateBundle(string name, IEnumerable<FileInfo> list)
            {
                name = name.Replace(root, "");

                var scene = list.Where(p => p.Extension == ".unity").ToList();
                if (scene.Count == 0)
                {
                    var fileInfo = new FileInfo($"test/{name}.bundle".Replace("\\", "@"));
                    fileInfo.Directory.Create();
                    WriteAllLines(fileInfo.FullName, list);
                }
                else
                {
                    var fileInfo = new FileInfo($"test/{name}.bundle".Replace("\\", "@"));
                    fileInfo.Directory.Create();
                    WriteAllLines(fileInfo.FullName, list.Except(scene));

                    fileInfo = new FileInfo($"test/{name}.scene.bundle".Replace("\\", "@"));
                    fileInfo.Directory.Create();
                    WriteAllLines(fileInfo.FullName, scene);
                }
            }

            void WriteAllLines(string fileInfo, IEnumerable<FileInfo> list)
            {
                var contents = list.Select(p => p.FullName).ToArray();
                if (contents.Length == 0)
                {
                    if (File.Exists(fileInfo))
                        File.Delete(fileInfo);
                    return;
                }
                File.WriteAllLines(fileInfo, contents);
            }
        }
    }

    public class Program4
    {
        public static void Main()
        {
            var root = Path.GetFullPath("C:/jenkins/OP/Android/OPProject/");

            //var dirRootCache = new DirectoryInfo(root).GetFiles("*.assetbundleroot", SearchOption.AllDirectories).ToDictionary(p => p.Directory, p => new HashSet<string>(File.ReadAllLines(p.FullName)));

            //File.WriteAllLines("rule.txt", dirRootCache.Select(p => $"{p.Key.FullName}**({string.Join("|", p.Value.ToArray())})"));

            //HashSet<string> main = new HashSet<string>();
            //foreach (var item in dirRootCache)
            //{
            //    foreach (var fileInfo in item.Key.GetFiles("*.*", SearchOption.AllDirectories))
            //    {
            //        string name = fileInfo.FullName.ToLower();
            //        if (item.Value.Contains(fileInfo.Extension))
            //        {
            //            var file = fileInfo.FullName.Replace(Environment.CurrentDirectory, "").Replace("\\", "/").TrimStart('/');

            //            main.Add(file);
            //        }
            //    }
            //}

            List<string> result = new List<string>();

            var lines = File.ReadAllLines($"{root}/Library/haahah1").Select(p => new FileInfo(Path.GetFullPath(root + p))).ToArray();
            var dirs2 = lines.GroupBy(p => p.Directory.FullName).ToDictionary(p => p.Key, p => p.ToArray());
            var cache = lines.GroupBy(p => p.Directory.Parent.FullName).ToDictionary(p => p.Key, p => new HashSet<string>(p.Select(o => o.Extension), StringComparer.OrdinalIgnoreCase));
            var results = cache.SelectMany(p => new DirectoryInfo(p.Key).GetFiles("*.*", SearchOption.AllDirectories).Where(o => p.Value.Contains(o.Extension))).ToList();
            var dirs = results.GroupBy(p => p.Directory.FullName).ToDictionary(p => p.Key, p => p.ToArray());

            foreach (var item in dirs)
            {
                var path = Path.Combine(item.Key, ".assetbundlerule");
                if (File.Exists(path))
                {
                    if (int.TryParse(File.ReadAllText(path), out int take))
                    {
                        //从前往后拾取几个_分割的
                        foreach (var files in GroupByName(item.Value, p => string.Join("_", Path.GetFileNameWithoutExtension(p.Name).Split(new[] { '_' }, take + 1).Take(take))))
                        {
                            //文件夹内的前缀相同的为一个bundle,无关后缀
                            CreateBundle(Path.Combine(item.Key, files.Key), files.Value);
                        }
                        continue;
                    }
                    else
                    {
                        foreach (var files in GroupByName(item.Value, p => Path.GetFileNameWithoutExtension(p.FullName)))
                        {
                            //文件夹内名称相同的为一个bundle,无关后缀
                            CreateBundle(Path.Combine(item.Key, files.Key), files.Value);
                        }
                    }
                }
                else
                {
                    //文件夹内的为一个bundle
                    var fileInfo = new FileInfo("test/" + item.Key.Replace(root, "").Replace("\\", "@") + ".bundle");
                    CreateBundle(item.Key, item.Value);
                }
            }

            Dictionary<string, List<FileInfo>> GroupByName(IEnumerable<FileInfo> fileInfos, Func<FileInfo, string> func)
            {
                return fileInfos.GroupBy(func, StringComparer.OrdinalIgnoreCase).OrderByDescending(p => p.Key.Length).ThenBy(p => p.Key).ToDictionary(p => p.Key, p => p.ToList());
            }


            void CreateBundle(string name, IEnumerable<FileInfo> list)
            {
                name = name.Replace(root, "");

                var scene = list.Where(p => p.Extension == ".unity").ToList();
                if (scene.Count == 0)
                {
                    var fileInfo = new FileInfo($"test/{name}".Replace("\\", "@"));
                    fileInfo.Directory.Create();
                    WriteAllLines(fileInfo.FullName, list);
                }
                else
                {
                    var fileInfo = new FileInfo($"test/{name}".Replace("\\", "@"));
                    fileInfo.Directory.Create();
                    WriteAllLines(fileInfo.FullName, list.Except(scene));

                    fileInfo = new FileInfo($"test/{name}.scene".Replace("\\", "@"));
                    fileInfo.Directory.Create();
                    WriteAllLines(fileInfo.FullName, scene);
                }
            }

            void WriteAllLines(string fileInfo, IEnumerable<FileInfo> list)
            {
                result.Add($"{Path.GetFileNameWithoutExtension(fileInfo).ToLower()}**({ string.Join("|", list.Select(p => p.Extension).Distinct().OrderBy(p => p))})");
                return;

                fileInfo = (fileInfo + ".bundle").ToLower();
                var contents = list.Select(p => p.FullName).ToArray();
                if (contents.Length == 0)
                {
                    if (File.Exists(fileInfo))
                        File.Delete(fileInfo);
                    return;
                }
                File.WriteAllLines(fileInfo, contents);
            }

            File.WriteAllLines("rule.txt", result.OrderBy(p => p).ThenBy(p => p.Length).Distinct());
        }
    }

    public class Program3
    {
        public static void Main()
        {

            //var copyList = "sdajfhsdngdklfjbhfskujdrinjm,fjd".ToCharArray();

            //copyList =  Enumerable.Repeat(copyList, 3).SelectMany(p => p).ToArray();

            //Console.WriteLine("sssss:"+Thread.CurrentThread.ManagedThreadId);
            //ConcurrentBag<bool> resultBool = new ConcurrentBag<bool>();
            //ParallelLoopResult result = Parallel.ForEach(copyList, new ParallelOptions() { MaxDegreeOfParallelism = 3 }, item =>
            //{
            //    Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}--->{resultBool.Count * 1f / copyList.Length}");
            //    resultBool.Add(true);
            //});

            //Console.WriteLine("dddd");


            Console.WriteLine(Path.IsPathRooted("http://"));
            Console.WriteLine(Path.IsPathRooted("fto://"));
            Console.WriteLine(Path.IsPathRooted("/haha/"));
            Console.WriteLine(Path.IsPathRooted("hahahhaha/"));
            Console.WriteLine(Path.IsPathRooted("C://hahahhaha/"));


            var cache = File.ReadAllLines("xxx.txt").GroupBy(p => Path.GetFileName(p), StringComparer.OrdinalIgnoreCase).ToDictionary(p => p.Key, p => p.ToList());


            Console.WriteLine(GetBundleScatterFolder("1d87eabc.ab"));//"000";
            Console.WriteLine(GetBundleScatterFolder("3cc635ce.ab"));//"000";
            Console.WriteLine(GetBundleScatterFolder("4b1b10f5.ab"));//"010";
            Console.WriteLine(GetBundleScatterFolder("1efcd231.ab"));//"010";
            Console.WriteLine(GetBundleScatterFolder("3a8da652.ab"));//"027";
            Console.WriteLine(GetBundleScatterFolder("2b0e57ef.ab"));//"027";


            var xxxx = "kkk_ggg_dd_d.xtx";
            var take = 3;
            xxxx = string.Join("_", xxxx.Split(new[] { '_' }, take + 1).Take(take));
            Console.WriteLine(xxxx);

        }


        public static string GetBundleScatterFolder(string abName)
        {
            int hashCode = (int)GetHashCode(abName);
            hashCode = hashCode >= 0 ? hashCode : -hashCode;
            return (hashCode % 400).ToString("D3");
        }

        public static uint GetHashCode(string content)
        {
            uint seed = 131; // 31 131 1313 13131 131313 etc..
            uint hash = 0;

            for (int i = 0; i < content.Length; i++)
            {
                hash = hash * seed + content[i];
            }
            return (hash & 0x7FFFFFFF);
        }
    }

}